package cn.itcast.bos.realm;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAccount;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.itcast.bos.domain.system.Permission;
import cn.itcast.bos.domain.system.Role;
import cn.itcast.bos.domain.system.User;
import cn.itcast.bos.service.system.PermissionService;
import cn.itcast.bos.service.system.RoleService;
import cn.itcast.bos.service.system.UserService;

//@Component("bosRealm")
public class BosRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;
	
	@Autowired
	private RoleService roleService;
	
	@Autowired
	private PermissionService permissionService;

	// shiro授权管理
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		System.out.println("授权...");
		//用于存储当前登录用户所具有的的角色和权限
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		//根据当前登录用户查询对应的角色和权限
		Subject subject = SecurityUtils.getSubject();
		//在认证管理中返回的的subject中获取当前的user
		User user = (User)subject.getPrincipal();
		//调用业务层,查询角色(某一个用户可能充当多个角色,利用T_ROLE_USER表关联)
		List<Role> rList = roleService.findByUser(user);
		for (Role role : rList) {
			authorizationInfo.addRole(role.getKeyword());
		}
		
		//调用业务层,查询权限(某一个用户可能具有多种权限)
		List<Permission> pList = permissionService.findByUser(user);
		for (Permission permission : pList) {
			authorizationInfo.addStringPermission(permission.getKeyword());
		}
		//将当前用户所具有的的所有角色和权限信息的对象返回,并以此作为依据进行访问的权限控制
		return authorizationInfo;
	}

	// shiro认证管理
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
			throws AuthenticationException {
		System.out.println("认证...");
		// 这里的token是由UserAction中的login方法传参过来,先要对token进行转型
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;

		// 根据用户名查询用户信息
		User user = userService.findByUsername(usernamePasswordToken.getUsername());

		// 查询到的用户对象进行判断
		if (user == null) {
			// 用户名不存在
			return null;
		} else {
			// 用户名存在
			// 参数一:期望登陆后,保存在subject中的信息
			// 参数二:密码,如果返回为null,则说明用户不存在,报出用户不存在的异常
			// 参数三:realm名称
			return new SimpleAccount(user, user.getPassword(), getName());
			//这里在返回了数据库中用户名的密码后,方法会将页面传入的密码和数据库中的密码进行比较,如果
			//不一致,则会报出密码不一致的异常.
		}

	}

}
